package com.mdevsol.apps.bread.generator.controller;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.annotation.PostConstruct;
import javax.enterprise.context.SessionScoped;
import javax.inject.Named;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.metamodel.Attribute;
import javax.persistence.metamodel.Attribute.PersistentAttributeType;
import javax.persistence.metamodel.EntityType;
import javax.persistence.metamodel.ManagedType;
import javax.persistence.metamodel.Metamodel;

import com.mdevsol.apps.bread.generator.model.MetaAtributo;
import com.mdevsol.apps.bread.generator.model.MetaEntidad;
import com.mdevsol.apps.bread.generator.model.MetaPaquete;
import com.mdevsol.apps.bread.generator.model.MetaViewElement;


@Named(value="conf")
@SessionScoped
public class ConfigurarApp implements Serializable{

	/**
	 * 
	 */
	private static final long serialVersionUID = -2752450867039027970L;

	@PersistenceContext(unitName="sample-entities")
	private EntityManager em;
	private MetaPaquete metaPaqueteActual;
	private MetaEntidad metaEntidadActual;
	private Map<MetaPaquete,List<MetaEntidad>> metadatos= new LinkedHashMap<MetaPaquete,List<MetaEntidad>>();
	private String atributos;
	
	@PostConstruct
	public void iniciar(){
		Metamodel metamodel = em.getMetamodel();		
		Set<EntityType<?>> allEntityTypes = metamodel.getEntities();
		Iterator<EntityType<?>> iter2 = allEntityTypes.iterator();
		System.out.println("lista de entity types");
		while(iter2.hasNext()){
			EntityType<?> x = iter2.next();
			String nombrePaquete = x.getJavaType().getPackage().getName();
			String nombreEntidad = x.getJavaType().getSimpleName();
			MetaPaquete mp = new MetaPaquete(nombrePaquete.trim());
			MetaEntidad ent = new MetaEntidad(nombreEntidad);
			mp.addEntidad(ent);
			System.out.println(" contiene ??? "+this.metadatos.containsKey(mp));
			if(!this.metadatos.containsKey(mp)){
				ArrayList<MetaEntidad> entPaq = new ArrayList<MetaEntidad>();
				this.metadatos.put(mp,entPaq);
			}
			this.metadatos.get(mp).add(ent);
		}
	}
	public String editar(){
		return null;
	}
	
	public String generar(){
		return null;
	}
	
	public String seleccionarEntidad(){
		Metamodel metamodel = em.getMetamodel();
		try {
			ManagedType<Object> ent = (ManagedType<Object>) metamodel.entity(Class.forName(this.metaPaqueteActual.getNombre()+"."+this.metaEntidadActual.getNombre() ));
			metaEntidadActual.setAtributos(new ArrayList<MetaAtributo>());
			Iterator<Attribute<? super Object, ?>> iter = ent.getAttributes().iterator();
			for(Attribute<? super Object, ?> att : ent.getAttributes()){
				MetaAtributo ma = new MetaAtributo(att.getName(), att.getName(), att.getJavaType().getCanonicalName());
				ma.setTipoRelacion(calcularMetaView(att.getPersistentAttributeType()));
				metaEntidadActual.addAtributo(ma);
			}
		}catch(Exception e) {
			e.printStackTrace();
		}
		return null;
	}

	public List<MetaEntidad> getEntidades() {
		if(this.metaPaqueteActual!= null ){
			return this.metadatos.get(metaPaqueteActual);
		}
		return this.metadatos.entrySet().iterator().next().getValue();
	}

	
	public Set<MetaPaquete> getPaquetes() {
		return this.metadatos.keySet();
	}


	public String getAtributos() {
		return atributos;
	}

	public void setAtributos(String atributos) {
		this.atributos = atributos;
	}

	public List<MetaAtributo> getMetaAtributos() {
		if (this.metaEntidadActual == null ) return null;
		return this.metaEntidadActual.getAtributos();
	}

	private MetaViewElement calcularMetaView(PersistentAttributeType pat){
		switch(pat){
			case BASIC:
				return MetaViewElement.TEXT;
			case MANY_TO_MANY:
				return MetaViewElement.POPUP_TABLE;
			case MANY_TO_ONE:
				return MetaViewElement.COMBO;
			case ONE_TO_MANY:
				return MetaViewElement.DETAIL_TABLE;
			case ONE_TO_ONE:
				return MetaViewElement.COMBO;
		}
		return MetaViewElement.TEXT;
	}

	public MetaEntidad getMetaEntidadActual() {
		return metaEntidadActual;
	}

	public void setMetaEntidadActual(MetaEntidad metaEntidadActual) {
		this.metaEntidadActual = metaEntidadActual;
	}

	public MetaPaquete getMetaPaqueteActual() {
		return metaPaqueteActual;
	}

	public void setMetaPaqueteActual(MetaPaquete metaPaqueteActual) {
		this.metaPaqueteActual = metaPaqueteActual;
	}
	
	
}